import json
import re
from urllib.parse import urljoin

import pytest
import requests
from utils.LogUtil import logger
from utils.YamlUtil import YamlUtil
from utils.iniUtil import IniUtil


class RequestCore:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(RequestCore, cls).__new__(cls)
            cls._instance.session = requests.Session()
            logger.info(f"RequestCore实例创建，ID: {id(cls._instance)}")
            logger.info(f"Session ID: {id(cls._instance.session)}")
        return cls._instance

    def __init__(self):
        if not hasattr(self, '_initialized'):
            self._initialized = True
            self.session = requests.Session()
            self.yaml_util = YamlUtil()
            self.cookies = None  # 显式存储 Cookies
            self.api_sys_url = IniUtil().read_settings_data()["host"]["api_sys_url"]
            self.api_login_url = IniUtil().read_settings_data()["host"]["api_login_url"]
            self.api_upload_url = IniUtil().read_settings_data()["host"]["api_upload_url"]
            self.api_admin_url = IniUtil().read_settings_data()["host"]["api_admin_url"]

    def do_request(self, url, method, **kwargs):
        # logger.info(f"Session ID: {id(self.session)}")
        # 打印接口数据
        self.request_log(url, method, **kwargs)
        if "login" in url:
            # url = self.api_login_url + url
            url = urljoin(self.api_login_url, url)
        elif "upload" in url or "make-cover" in url:
            url = urljoin(self.api_upload_url, url)
        elif "modelVerify" in url or "personalVerify" in url:
            url = urljoin(self.api_admin_url, url)
        else:
            url = urljoin(self.api_sys_url, url)

        # 自动获取CSRF Token而不是硬编码
        if "data" in kwargs and isinstance(kwargs["data"], dict):
            kwargs["data"]["scrfCode"] = self._get_csrf_token()

        # 移除手动设置的Cookie头，让Session自动管理
        if "headers" in kwargs and "Cookie" in kwargs["headers"]:
            kwargs["headers"].pop("Cookie")

        response = self.session.request(url=url, method=method, verify=False, **kwargs)

        return self._process_response(response)

    def _process_response(self, response):
        """处理响应数据，提取有效JSON部分"""
        try:
            # 先尝试直接解析JSON
            # print(response.text)
            data = response.json()
            logger.info(f"接口响应数据:\n{json.dumps(data, indent=2, ensure_ascii=False)}")
            return data
        except json.JSONDecodeError:
            # 如果直接解析失败，尝试提取JSON部分
            json_match = re.search(r'\{([^}]+)\}', response.text, re.DOTALL)
            if json_match:
                try:
                    data = json.loads(json_match.group())
                    logger.info(f"提取的JSON数据:\n{json.dumps(data, indent=2, ensure_ascii=False)}")
                    return data
                except json.JSONDecodeError as e:
                    error_msg = f"JSON解析失败: {str(e)}\n原始内容: {response.text[:500]}..."  # 限制日志长度
                    logger.error(error_msg)
                    raise ValueError(error_msg)
            else:
                error_msg = f"响应中未找到有效的JSON数据\n原始内容: {response.text[:500]}..."
                logger.error(error_msg)
                raise ValueError(error_msg)

    def request_log(self, url, method, **kwargs):
        data = dict(kwargs).get("data")
        json_data = dict(kwargs).get("json")
        params = dict(kwargs).get("params")
        headers = dict(kwargs).get("headers")
        files = dict(kwargs).get("files")
        if "login" in url:
            logger.info(f"接口请求地址:{self.api_login_url + url}")
        elif "upload" in url or "make-cover" in url:
            logger.info(f"接口请求地址:{self.api_upload_url + url}")
        else:
            logger.info(f"接口请求地址:{self.api_sys_url + url}")
        logger.info(f"接口请求方法:{method}")
        if headers is not None:
            logger.info(f"接口请求头headers数据:\n{json.dumps(headers, indent=2, ensure_ascii=False)}")
        if data is not None:
            logger.info(f"接口请求data数据:\n{json.dumps(data, indent=2, ensure_ascii=False)}")
        if files is not None:
            logger.info(f"接口请求files数据:\n{files}")
        if json_data is not None:
            logger.info(f"接口请求json数据:\n{json.dumps(json_data, indent=2, ensure_ascii=False)}")
        if params is not None:
            logger.info(f"接口请求params数据:\n{json.dumps(params, indent=2, ensure_ascii=False)}")

    def _get_csrf_token(self):
        """获取CSRF Token的三种方式"""
        # 1. 从已有cookie中获取
        if "PHPSESSScrf" in self.session.cookies:
            return self.session.cookies["PHPSESSScrf"]
        # 2. 从登录页面获取(如果需要)
        try:
            login_page = self.session.get("http://login.galawo.com:8081/")
            login_page.raise_for_status()
            # print(login_page.text)
            # 这里可以添加从HTML中解析CSRF Token的逻辑
            # 例如: soup.find('input', {'name': 'scrfCode'})['value']
        except requests.exceptions.RequestException as e:
            logger.error(f"获取登录页面失败: {e}")
        # 3. 使用默认值(最后保障)
        return "04fbc58ffe80f3cd41bd08ac29cad14b"

# if __name__ == '__main__':
#     resq = RequestCore()
#     print(resq.request("/uploadV2", "post"))
